﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Security.Principal;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using System.ComponentModel;

namespace Citi.Helpers
{
    public class ImpersonateUser : IDisposable
    {
        [DllImport("advapi32.dll", SetLastError = true)]
        public static extern bool LogonUser(String lpszUsername, String lpszDomain,
        String lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        public extern static bool CloseHandle(IntPtr handle);

        private const int LOGON32_PROVIDER_DEFAULT = 0;
        private const int LOGON32_LOGON_INTERACTIVE = 2;

        private string m_Domain;
        private string m_Password;
        private string m_Username;
        private IntPtr m_Token;

        private WindowsImpersonationContext m_Context = null;

        protected bool IsInContext
        {
            get { return m_Context != null; }
        }

        [PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
        public void Impersonate(string domain, string username, string password)
        {
            m_Domain = domain;
            m_Username = username;
            m_Password = password;

            if (this.IsInContext) return;
            m_Token = new IntPtr(0);
            try
            {
                m_Token = IntPtr.Zero;
                bool logonSuccessfull = LogonUser(
                   m_Username,
                   m_Domain,
                   m_Password,
                   LOGON32_LOGON_INTERACTIVE,
                   LOGON32_PROVIDER_DEFAULT,
                   ref m_Token);
                if (logonSuccessfull == false)
                {
                    int error = Marshal.GetLastWin32Error();
                    throw new Win32Exception(error);
                }
                WindowsIdentity identity = new WindowsIdentity(m_Token);
                m_Context = identity.Impersonate();
            }
            catch (Exception exception)
            {
                // Catch exceptions here
            }
        }

        [PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
        public void Leave()
        {
            if (this.IsInContext == false) return;
            m_Context.Undo();

            if (m_Token != IntPtr.Zero) CloseHandle(m_Token);
            m_Context = null;
        }

        public void Dispose()
        {
            Leave();
        }
    }

        //[DllImport("advapi32.dll", SetLastError = true)]
        //public static extern bool LogonUser(
        //String lpszUsername,
        //String lpszDomain,
        //String lpszPassword,
        //int dwLogonType,
        //int dwLogonProvider,
        //ref IntPtr phToken);
        //[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        //public extern static bool CloseHandle(IntPtr handle);
        //private static IntPtr tokenHandle = new IntPtr(0);
        //private static WindowsImpersonationContext impersonatedUser;
        //// If you incorporate this code into a DLL, be sure to demand that it
        //// runs with FullTrust.
        //[PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
        //public void Impersonate(string domainName, string userName, string password)
        //{
        //    //try
        //    {
        //        // Use the unmanaged LogonUser function to get the user token for
        //        // the specified user, domain, and password.
        //        const int LOGON32_PROVIDER_DEFAULT = 0;
        //        // Passing this parameter causes LogonUser to create a primary token.
        //        const int LOGON32_LOGON_INTERACTIVE = 2;
        //        tokenHandle = IntPtr.Zero;
        //        // ---- Step - 1
        //        // Call LogonUser to obtain a handle to an access token.
        //        bool returnValue = LogonUser(
        //        userName,
        //        domainName,
        //        password,
        //        LOGON32_LOGON_INTERACTIVE,
        //        LOGON32_PROVIDER_DEFAULT,
        //        ref tokenHandle) // tokenHandle - new security token
        //        if (false == returnValue)
        //        {
        //            int ret = Marshal.GetLastWin32Error();
        //            throw new System.ComponentModel.Win32Exception(ret);
        //        }
        //        // ---- Step - 2
        //        var newId = new WindowsIdentity(tokenHandle);
        //        // ---- Step - 3
        //        {
        //            impersonatedUser = newId.Impersonate();
        //        }
        //    }
        //}
        //// Stops impersonation
        //public void Undo()
        //{
        //    if (impersonatedUser == null) return;

        //    impersonatedUser.Undo();
        //    // Free the tokens.
        //    if (tokenHandle != IntPtr.Zero)
        //    {
        //        CloseHandle(tokenHandle);
        //    }
        //}

        //public void Dispose()
        //{
        //    Undo(); 
        //}

      

    //public class Impersonate
    //{
    //#region 'Impersonation'

    //// obtains user token
    //[DllImport("advapi32.dll", SetLastError = true)]
    //public static extern bool LogonUser(string pszUsername, string pszDomain, string pszPassword,
    //    int dwLogonType, int dwLogonProvider, ref IntPtr phToken);

    //// closes open handes returned by LogonUser
    //[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
    //public extern static bool CloseHandle(IntPtr handle);

    //public IntPtr ImpersonateUser(string sUsername, string sDomain, string sPassword)
    //{
    //    // initialize token
    //    var pExistingTokenHandle = new IntPtr(0);

    //    // if domain name was blank, assume local machine
    //    if (sDomain == string.Empty)
    //        sDomain = Environment.MachineName;

    //    try
    //    {
    //        string sResult = null;

    //        const int logon32ProviderDefault = 0;
    //        const int logon32LogonInteractive = 2;
    //        const int logon32LogonNewCredentials = 9;

    //        // get handle to token
    //        bool bImpersonated = LogonUser(sUsername, sDomain, sPassword,
    //            logon32LogonNewCredentials, logon32ProviderDefault, ref pExistingTokenHandle);

    //        // did impersonation fail?
    //        if (false == bImpersonated)
    //        {
    //            int nErrorCode = Marshal.GetLastWin32Error();
    //            sResult = "LogonUser() failed with error code: " + nErrorCode + "\r\n";

    //            // show the reason why LogonUser failed
    //            //MessageBox.Show(sResult, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
    //        }

    //        // Get identity before impersonation
    //        sResult += "Before impersonation: " + WindowsIdentity.GetCurrent().Name + "\r\n";

    //        return pExistingTokenHandle;
    //    }
    //    catch (Exception ex)
    //    {
    //        throw ex;
    //    }
    //}

    //public bool FreeImpersonationResource(IntPtr token)
    //{
    //    // close handle(s)
    //    if (token != IntPtr.Zero)
    //        return CloseHandle(token);
    //    else return true;
    //}

    //#endregion
    //}
}
